import {
  MiddlewareConsumer,
  Module,
  NestModule,
  RequestMethod,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import envConfig from '../config/env';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Roles } from './entities/roles.entity';
import { RolesModule } from './roles/roles.module';
import { UserController } from './user/user.controller';
import { UserService } from './user/user.service';
import { UserModule } from './user/user.module';
import { MenuController } from './menu/menu.controller';
import { MenuModule } from './menu/menu.module';
import { Menu } from './entities/menu.entity';

// @Module 装饰器是一个函数，它接受一个对象作为参数，这个对象包含了模块的元数据
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: [envConfig.path],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        entities: [User, Roles, Menu],
        host: configService.get('DB_HOST'),
        port: configService.get<number>('DB_PORT'), // 端口号
        username: configService.get('DB_USER'), // 用户名
        password: configService.get('DB_PASSWD'), // 密码
        database: configService.get('DB_DATABASE'), //数据库名
        timezone: '+08:00', //服务器上配置的时区
        // synchronize: true, //根据实体自动创建数据库表， 生产环境建议关闭
      }),
    }),
    TypeOrmModule.forFeature([User]),
    UserModule,
    RolesModule,
    MenuModule,
  ], // 导入其他模块
  controllers: [AppController, UserController, MenuController], //此模块中定义的必须实例化的控制器集
  providers: [AppService, UserService], // 将由Nest注入实例化并且至少可以在该模块中共享的提供程序
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes({
      path: '{*splat}',
      method: RequestMethod.ALL,
    });
  }
}
